﻿using System;
using System.Collections.Generic;

namespace homework02_1
{
    // 自定义异常类：表示坏的钞票
    class BadCashException : Exception
    {
        public BadCashException(string message) : base(message) { }
    }

    // 事件参数类：表示大额取款事件
    class BigMoneyArgs : EventArgs
    {
        public Account Account { get; } // 取款的账号
        public decimal Amount { get; } // 取款金额

        public BigMoneyArgs(Account account, decimal amount)
        {
            Account = account;
            Amount = amount;
        }
    }

    // 账号类
    class Account
    {
        public string AccountNumber { get; } // 账号
        public string OwnerName { get; } // 户主名
        public decimal Balance { get; protected set; } // 余额

        // 构造函数
        public Account(string accountNumber, string ownerName, decimal initialBalance)
        {
            AccountNumber = accountNumber;
            OwnerName = ownerName;
            Balance = initialBalance;
        }

        // 存款
        public virtual void Deposit(decimal amount)
        {
            if (amount <= 0)
                throw new ArgumentException("存款金额必须大于0。");
            Balance += amount;
            Console.WriteLine($"{OwnerName} 存款 {amount} 元，余额为 {Balance} 元。");
        }

        // 取款
        public virtual void Withdraw(decimal amount)
        {
            if (amount <= 0)
                throw new ArgumentException("取款金额必须大于0。");
            if (amount > Balance)
                throw new InvalidOperationException("余额不足。");
            Balance -= amount;
            Console.WriteLine($"{OwnerName} 取款 {amount} 元，余额为 {Balance} 元。");
        }
    }

    // 信用账号类（继承自Account）
    class CreditAccount : Account
    {
        public decimal CreditLimit { get; } // 信用额度

        // 构造函数
        public CreditAccount(string accountNumber, string ownerName, decimal initialBalance, decimal creditLimit)
            : base(accountNumber, ownerName, initialBalance)
        {
            CreditLimit = creditLimit;
        }

        // 重写取款方法，支持信用额度
        public override void Withdraw(decimal amount)
        {
            if (amount <= 0)
                throw new ArgumentException("取款金额必须大于0。");
            if (amount > Balance + CreditLimit)
                throw new InvalidOperationException("超过信用额度。");
            Balance -= amount;
            Console.WriteLine($"{OwnerName} 取款 {amount} 元，余额为 {Balance} 元，信用额度为 {CreditLimit} 元。");
        }
    }

    // ATM类
    class ATM
    {
        // 定义大额取款事件
        public event EventHandler<BigMoneyArgs> BigMoneyFetched;

        // 取款方法
        public void Withdraw(Account account, decimal amount)
        {
            try
            {
                // 模拟坏钞率30%
                Random random = new Random();
                if (random.Next(0, 100) < 30)
                    throw new BadCashException("取款失败：检测到坏的钞票。");

                // 调用账号的取款方法
                account.Withdraw(amount);

                // 如果取款金额大于10000，触发大额取款事件
                if (amount > 10000)
                    BigMoneyFetched?.Invoke(this, new BigMoneyArgs(account, amount));
            }
            catch (BadCashException ex)
            {
                Console.WriteLine(ex.Message); // 捕获并处理坏钞异常
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message); // 捕获并处理其他异常
            }
        }
    }

    // 银行类
    class Bank
    {
        private List<Account> accounts = new List<Account>(); // 存储所有账号

        // 添加账号
        public void AddAccount(Account account)
        {
            accounts.Add(account);
        }

        // 根据账号号查找账号
        public Account GetAccount(string accountNumber)
        {
            return accounts.Find(a => a.AccountNumber == accountNumber);
        }
    }

    // 主程序
    class Program
    {
        static void Main1(string[] args)
        {
            // 创建银行
            Bank bank = new Bank();

            // 创建普通账号和信用账号
            Account account1 = new Account("123456", "张三", 5000);
            CreditAccount account2 = new CreditAccount("654321", "李四", 10000, 5000);

            // 将账号添加到银行
            bank.AddAccount(account1);
            bank.AddAccount(account2);

            // 创建ATM
            ATM atm = new ATM();

            // 注册大额取款事件
            atm.BigMoneyFetched += (sender, e) =>
            {
                Console.WriteLine($"\n警告：{e.Account.OwnerName} 从账号 {e.Account.AccountNumber} 取款 {e.Amount} 元！");
            };

            // 模拟ATM操作
            Console.WriteLine("========== 模拟ATM操作 ==========");

            // 显示初始余额
            Console.WriteLine("\n初始余额：");
            Console.WriteLine($"{account1.OwnerName} 的账号 {account1.AccountNumber} 余额为 {account1.Balance} 元。");
            Console.WriteLine($"{account2.OwnerName} 的账号 {account2.AccountNumber} 余额为 {account2.Balance} 元，信用额度为 {account2.CreditLimit} 元。");

            // 存款操作
            Console.WriteLine("\n存款操作：");
            account1.Deposit(1000); // 张三存款1000元
            account2.Deposit(2000); // 李四存款2000元

            // 取款操作
            Console.WriteLine("\n取款操作：");
            atm.Withdraw(account1, 2000); // 张三取款2000元
            atm.Withdraw(account2, 12000); // 李四取款12000元（触发大额取款事件）
            atm.Withdraw(account1, 100); // 张三取款100元（模拟坏钞）

            // 显示最终余额
            Console.WriteLine("\n最终余额：");
            Console.WriteLine($"{account1.OwnerName} 的账号 {account1.AccountNumber} 余额为 {account1.Balance} 元。");
            Console.WriteLine($"{account2.OwnerName} 的账号 {account2.AccountNumber} 余额为 {account2.Balance} 元，信用额度为 {account2.CreditLimit} 元。");

            // 异常操作测试
            Console.WriteLine("\n异常操作测试：");
            try
            {
                account1.Withdraw(-100); // 取款金额为负数
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            try
            {
                account1.Withdraw(10000); // 余额不足
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            try
            {
                account2.Withdraw(20000); // 超过信用额度
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}
